package online

import (
	"server/common"
	"sync"
	"time"
)

type UserInfo struct {
	ServiceInfo common.ServiceInfo
	UserId      string
	CreateTime  time.Time
	ConnId      string // Connection ID, if applicable
}

type UserManager struct {
	users map[string]*UserInfo
	mtx   sync.RWMutex
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func NewUserManager() *UserManager {
	return &UserManager{
		users: make(map[string]*UserInfo),
	}
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (rm *UserManager) AddUser(userId string, serviceInfo common.ServiceInfo, connId string) {
	rm.mtx.Lock()
	defer rm.mtx.Unlock()
	rm.users[userId] = &UserInfo{
		ServiceInfo: serviceInfo,
		UserId:      userId,
		CreateTime:  time.Now(),
		ConnId:      connId,
	}
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (rm *UserManager) RemoveUser(userId string) {
	rm.mtx.Lock()
	defer rm.mtx.Unlock()
	delete(rm.users, userId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (rm *UserManager) UserExists(userId string) bool {
	rm.mtx.RLock()
	defer rm.mtx.RUnlock()
	_, exists := rm.users[userId]
	return exists
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (rm *UserManager) RemoveUserByConnId(connId string) {
	rm.mtx.Lock()
	defer rm.mtx.Unlock()
	for userId, user := range rm.users {
		if user.ConnId == connId {
			delete(rm.users, userId)
			break
		}
	}
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (rm *UserManager) GetUserByUserId(userId string) *UserInfo {
	rm.mtx.RLock()
	defer rm.mtx.RUnlock()
	user, exists := rm.users[userId]
	if !exists {
		return nil
	}
	return user
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (rm *UserManager) GetUserByConnId(connId string) *UserInfo {
	rm.mtx.RLock()
	defer rm.mtx.RUnlock()
	for _, user := range rm.users {
		if user.ConnId == connId {
			return user
		}
	}
	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (rm *UserManager) GetUserListWithoutSelf(selfUserId string) []*UserInfo {
	rm.mtx.RLock()
	defer rm.mtx.RUnlock()
	var userList []*UserInfo
	for userId, user := range rm.users {
		if userId != selfUserId {
			userList = append(userList, user)
		}
	}
	return userList
}
